package com.originskyseed.platform.log.service.impl;

import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;
import com.originskyseed.platform.common.logtype.LogTypeEnums;
import com.originskyseed.platform.core.base.BasePage;
import com.originskyseed.platform.core.mongodb.api.MongoUtil;
import com.originskyseed.platform.core.tenant.util.TenantCodeUtil;
import com.originskyseed.platform.core.util.bean.PrimaryKeyGeneratorUtil;
import com.originskyseed.platform.log.model.OperLog;
import com.originskyseed.platform.log.service.ISysLogService;

/**
 *
 * @Description
 * @Author HanGuJi @Date2019/7/31 9:55
 * @Version V1.0
 **/
@DubboService
@Component("sysLogService")
public class SysLogServiceImpl implements ISysLogService {

	// 日志记录表
	private final static String OPER_LOG = "oper_log";

	@Override
	public Boolean saveLog(OperLog operLog) {
		boolean returnRes = false;
		JSONObject jsonObject = new JSONObject();
		String id = PrimaryKeyGeneratorUtil.getInstance().getRandomKey();
		// 设置mongodb数据
		jsonObject.put("id", id);
		jsonObject.put("user_id", operLog.getUserId());
		jsonObject.put("user_name", operLog.getUserName());
		jsonObject.put("user_account", operLog.getUserAccount());
		jsonObject.put("method", operLog.getMethod());
		jsonObject.put("ip", operLog.getIp());
		jsonObject.put("browner_no", operLog.getBrownerNo());
		jsonObject.put("module", operLog.getModule());
		jsonObject.put("os_no", operLog.getOsNo());
		jsonObject.put("operation_desc", operLog.getOperationDesc());
		jsonObject.put("status", operLog.getStatus());
		jsonObject.put("source", operLog.getSource());
		jsonObject.put("msg", operLog.getMsg());
		jsonObject.put("create_time", new Date());
		try {
			MongoUtil.getInstance().insert(jsonObject, OPER_LOG);
			returnRes = true;
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return returnRes;
	}

	@Override
	public Boolean saveLog(OperLog operLog, String tenantCode) {
		if (StringUtils.isNotEmpty(tenantCode)) {
			TenantCodeUtil.getInstance().createServerTenantCode(tenantCode);
		}
		return saveLog(operLog);
	}

	@Override
	public BasePage<OperLog> getOperLogList(Map<String, Object> params, BasePage<OperLog> page) throws Exception {
		Query query = getQuery(params);
		query.with(Sort.by(new Sort.Order(Sort.Direction.DESC, "create_time")));
		List<OperLog> list = null;
		try {
			list = MongoUtil.getInstance().selectListByPage(query, page, OperLog.class, OPER_LOG);
			// 获取总数
			Long totalNum = MongoUtil.getInstance().selectCountByQuery(query, OPER_LOG);
			page.setTotalRecord(Integer.valueOf(String.valueOf(totalNum)));
			page.setResults(list);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return page;
	}

	@Override
	public BasePage<OperLog> getOperLogList(Map<String, Object> params, BasePage<OperLog> page, String tenantCode) throws Exception {
		if (StringUtils.isNotEmpty(tenantCode)) {
			TenantCodeUtil.getInstance().createServerTenantCode(tenantCode);
		}
		return getOperLogList(params, page);
	}

	/**
	 * 公共查询条件
	 *
	 * @param params
	 * @return
	 * @throws ParseException
	 */
	private Query getQuery(Map<String, Object> params) throws ParseException {
		Query query = new Query();
		Criteria criteria = new Criteria();

		// 判断是什么日志记录
		if (StringUtils.equals("1", (String) params.get("logType"))) {
			// 查询登录，登出，注册
			criteria.and("module").in(LogTypeEnums.Login.getModule(), LogTypeEnums.LOGOUT.getModule(), LogTypeEnums.REGISTER.getModule());
		} else {
			if (ObjectUtils.allNotNull(params.get("module"))) {
				criteria.and("module").regex(".*" + ((String) params.get("module")).trim() + ".*");
			} else {
				// 不包含 登录，登出，注册的模块
				criteria.and("module").nin(LogTypeEnums.Login.getModule(), LogTypeEnums.LOGOUT.getModule(), LogTypeEnums.REGISTER.getModule());
			}
		}
		// 删除module和logType
		params.remove("module");
		params.remove("logType");
		if (ObjectUtils.allNotNull(params.get("startTime")) && ObjectUtils.allNotNull(params.get("endTime"))) {
			Calendar cld = getCalendar((String) params.get("endTime"));
			criteria.andOperator(Criteria.where("create_time").gte(DateUtils.parseDate((String) params.get("startTime"), "yyyy-MM-dd")), Criteria.where("create_time").lte(cld.getTime()));
			params.remove("startTime");
			params.remove("endTime");
		}
		params.forEach((k, v) -> {
			if (ObjectUtils.allNotNull(v)) {
				if (k.contains("userName")) {
					criteria.and("user_name").regex(".*" + ((String) v).trim() + ".*");
				} else if (k.contains("userAccount")) {
					criteria.and("user_account").regex(".*" + ((String) v).trim() + ".*");
				} else if (k.contains("operationDesc")) {
					criteria.and("operation_desc").regex(".*" + ((String) v).trim() + ".*");
				} else if (k.contains("method")) {
					criteria.and("method").regex(".*" + ((String) v).trim() + ".*");
				} else if (k.contains("ip")) {
					criteria.and("ip").regex(".*" + ((String) v).trim() + ".*");
				} else if (k.contains("status")) {
					criteria.and("status").regex(".*" + ((String) v).trim() + ".*");
				} else if (k.contains("source")) {
					criteria.and("source").regex(".*" + ((String) v).trim() + ".*");
				} else if (k.contains("startTime")) {
					try {
						criteria.and("create_time").gte(DateUtils.parseDate((String) v, "yyyy-MM-dd"));
					} catch (ParseException e) {
						e.printStackTrace();
					}
				} else if (k.contains("endTime")) {
					Calendar cld = getCalendar((String) v);
					criteria.and("create_time").lte(cld.getTime());
				}
			}
		});

		query.addCriteria(criteria);
		return query;
	}

	@Override
	public List<OperLog> selectListByMap(Map<String, Object> params) throws Exception {
		// 定义mongodb的查询条件
		Query query = getQuery(params);
		query.with(Sort.by(new Sort.Order(Sort.Direction.DESC, "create_time")));
		BasePage<OperLog> page = new BasePage<>();
		page.setPageNo(0);
		page.setPageSize(0);
		List<OperLog> list = MongoUtil.getInstance().selectListByPage(query, page, OperLog.class, OPER_LOG);
		return list;
	}

	@Override
	public Boolean deleteLog(Map<String, Object> params) throws Exception {
		Query query = getQuery(params);
		BasePage<OperLog> page = new BasePage<>();
		long l = MongoUtil.getInstance().deleteByQuery(query, OPER_LOG);
		if (l > 0) {
			return true;
		}
		return false;
	}

	@Override
	public Boolean deleteLog(Map<String, Object> params, String tenantCode) throws Exception {
		if (StringUtils.isNotEmpty(tenantCode)) {
			TenantCodeUtil.getInstance().createServerTenantCode(tenantCode);
		}
		return deleteLog(params);
	}

	@Override
	public List<OperLog> selectListByMap(Map<String, Object> params, String tenantCode) throws Exception {
		if (StringUtils.isNotEmpty(tenantCode)) {
			TenantCodeUtil.getInstance().createServerTenantCode(tenantCode);
		}
		return selectListByMap(params);
	}

	/**
	 * 获取加一天的时间
	 *
	 * @param
	 * @return
	 */
	private Calendar getCalendar(String value) {
		Date endTime = null;
		try {
			endTime = DateUtils.parseDate(value, "yyyy-MM-dd");
		} catch (ParseException e) {
			e.printStackTrace();
		}
		Calendar cld = Calendar.getInstance();
		cld.setTime(endTime);
		cld.add(Calendar.DATE, 1);
		return cld;
	}

}
